#ifndef __SPINLOCK_H
#define __SPINLOCK_H
#include "stdtype.h"
#include "cpu.h"

/**
 * not use the `mx_atom_flag_lock` because of the cross-reference,
 * instead, it uses `mx_atom_set8test` because it is not using structure which contain in header file
 */

/**
 * spin lock struct definition
 */
typedef struct
{
    mx_usize_t istate;          // the local interrupt state when lock
    volatile mx_usize_t flag;   // the lock flag
} mx_spinlock_t, *mx_spinlock_pt;

/* initialize the spin lock */
void mx_spinlock_init (mx_spinlock_pt pspinlock);
/* lock the specified spin lock, keep trying until success */
void mx_spinlock_lock (mx_spinlock_pt pspinlock);
/* try lock the specified spin lock */
mx_bool_t mx_spinlock_trylock (mx_spinlock_pt pspinlock);
/* unlock the specified spin lock */
void mx_spinlock_unlock (mx_spinlock_pt pspinlock);

/// ------------------------------------------------------------------------ rw spinlock

/**
 * rw spin lock struct definition
 */
typedef struct
{
    mx_usize_t istates[MX_CPU_NUM]; // the local interrupt state when lock
    volatile mx_usize_t rw;         // reader-count or write-flag(MX_SPINLOCK_RW_WRITING)
    volatile mx_usize_t flag;       // the lock for `rw` mutually exclusive modifications
} mx_spinlock_rw_t, *mx_spinlock_rw_pt;

/* rw-spinlock initialize */
void mx_spinlock_rw_init (mx_spinlock_rw_pt psrw);
/* get the read lock of rw-spinlock */
void mx_spinlock_rw_rlock (mx_spinlock_rw_pt psrw);
/* try to get the read lock of rw-spinlock */
mx_bool_t mx_spinlock_rw_tryrlock (mx_spinlock_rw_pt psrw);
/* get the write lock of rw-spinlock */
void mx_spinlock_rw_wlock (mx_spinlock_rw_pt psrw);
/* try to get the write lock of rw-spinlock */
mx_bool_t mx_spinlock_rw_trywlock (mx_spinlock_rw_pt psrw);
/* unlock the rw-spinlock, both rlock and wlock can call this funciton to unlock */
void mx_spinlock_rw_unlock (mx_spinlock_rw_pt psrw);

#endif
